package com.bowlofnoodles.truffles;

/**
 * 
 * The GAE backend for the TruffleSearchClient doesn't
 * implement any kind of security. One could potentially
 * craft (in)appropriate queries to this page with something like cURL
 * and fill up the database with nonsense or read data from the
 * database if the parameters for the desired field are known.
 * 
 * For this reason, there is no storing of google account
 * passwords of any kind.
 * 
 * 
 */

import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

public class TruffleGenericServlet extends GenericServlet {

	
	private static final long serialVersionUID = 1L;
	
	private static final boolean DEBUG = false;
	
	@Override
	public void service(ServletRequest req, ServletResponse resp)
			throws ServletException, IOException {
		resp.setContentType("text/plain");
		
		if (DEBUG) { echo(req, resp); return; }
		
		String what = req.getParameter("action");
		
		// actions from the client
		if (what != null) {
			if (what.equals("doLogin")) {
				checkIfRegistered(req, resp);
			} else if (what.equals("doRegister")) {
				register(req,resp);
			} else if (what.equals("getInfo")) {
				returnInfo(req,resp);
			} else if (what.equals("toggleSearch")) {
				toggleSearching(req,resp);
			} else if (what.equals("setInfo")) {
				setProperty(req,resp);
			}
			return;
		}

	}
	
	/**
	 * This is a generic request that gets some info from a field.
	 * I wrote it after the other methods, after I realized a more generic
	 * query might be more useful.
	 * @param req The request from the client.
	 * @param resp The response to which to write.
	 * @throws IOException
	 */
	private void returnInfo(ServletRequest req, ServletResponse resp) throws IOException {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		// construct query
		Query q = new Query("User");
		q.addFilter("userAccount", Query.FilterOperator.EQUAL, req.getParameter("userAccount"));
		PreparedQuery pq = datastore.prepare(q);
		
		Entity result;
		
		if ((result = pq.asSingleEntity()) != null) {
			resp.getWriter().print(result.getProperty(req.getParameter("parameter")));
		} else {
			resp.getWriter().print(-1);
		}
		
	}
	
	/**
	 * Generic "set" action in the database.
	 * @param req
	 * @param resp
	 * @throws IOException
	 */
	private void setProperty(ServletRequest req, ServletResponse resp) throws IOException {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		// construct query
		Query q = new Query("User");
		q.addFilter("userAccount", Query.FilterOperator.EQUAL, req.getParameter("userAccount"));
		PreparedQuery pq = datastore.prepare(q);
		
		Entity result;
		
		if ((result = pq.asSingleEntity()) != null) {
			// BE CAREFUL OF THIS LATER, IDIOT
			if (req.getParameter("value").contains("true")) {
				result.setProperty(req.getParameter("parameter"),true);
			} else if (req.getParameter("value").contains("false")) {
				result.setProperty(req.getParameter("parameter"),false);
			} else {
				result.setProperty(req.getParameter("parameter"),req.getParameter("value"));
			}
			datastore.put(result);
		} else {
			resp.getWriter().print(-1);
		}
		
	}

	/**
	 * Determine if a userAccount exists in the database and respond to the client.
	 * @param req
	 * @param resp
	 * @throws IOException
	 */
	private void checkIfRegistered(ServletRequest req, ServletResponse resp) throws IOException {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		// construct query
		Query q = new Query("User");
		q.addFilter("userAccount", Query.FilterOperator.EQUAL, req.getParameter("userAccount"));
		
		// actually try to get queried item from datastore
		PreparedQuery pq = datastore.prepare(q);
		
		Entity result;
		
		if ((result = pq.asSingleEntity()) != null) {
			// TODO: tell server to start/continue looking for truffles for this user
			resp.getWriter().print("welcome back");
		} else {
			// sign em up, start em up
			resp.getWriter().print("hajimemashite");
		}
		
	}
	
	/**
	 * Create a new user and store them in the database.
	 * @param req
	 * @param resp
	 * @throws IOException
	 */
	private void register(ServletRequest req, ServletResponse resp) throws IOException {
		
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Entity result;
		result = new Entity("User");
		System.out.println(req.getParameter("userAccount"));
		result.setProperty("userAccount", req.getParameter("userAccount"));
		result.setProperty("c2dm_reg_id", req.getParameter("c2dm_reg_id"));
		result.setProperty("gramsFound", 0);
		result.setProperty("joinDate", new Date());
		result.setProperty("searchingNow", true);
		datastore.put(result);
		
	}
	
	/**
	 * Flip the searchingNow boolean.
	 * @param req
	 * @param resp
	 * @throws IOException
	 */
	private void toggleSearching(ServletRequest req, ServletResponse resp) throws IOException {
		
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		// construct query
		Query q = new Query("User");
		q.addFilter("userAccount", Query.FilterOperator.EQUAL, req.getParameter("userAccount"));
		
		// actually try to get queried item from datastore
		PreparedQuery pq = datastore.prepare(q);
		
		Entity result;
		
		if ((result = pq.asSingleEntity()) != null) {
			result.setProperty("searchingNow", ! Boolean.valueOf((String) result.getProperty("searchingNow")));
			datastore.put(result);
		} 
		
	}
	

	/**
	 * debug/testing method.
	 * @param req
	 * @param resp
	 * @throws IOException
	 */
	private void echo(ServletRequest req, ServletResponse resp) throws IOException {
		Enumeration enume = req.getParameterNames();
		
		while (enume.hasMoreElements()) {
			String key = (String) enume.nextElement();
			resp.getWriter().println(key + ": " + req.getParameter(key));
		}
		
		
		
	}

}
